/*
 * @Description:
 * @Author: 张效玮2 yythis@163.com
 * @Date: 2025-08-11 10:05:29
 * @LastEditors: 张效玮2
 * @LastEditTime: 2025-08-15 10:21:28
 */
import { getActiveThemeName, getThemeUserOverride, setActiveThemeName, setThemeUserOverride } from "@@/utils/cache/local-storage"
import { setCssVar } from "@@/utils/css"

const DEFAULT_THEME_NAME = "normal"

type DefaultThemeName = typeof DEFAULT_THEME_NAME

/** 注册的主题名称, 其中 DefaultThemeName 是必填的 */
export type ThemeName = DefaultThemeName | "dark"

interface ThemeList {
  title: string
  name: ThemeName
}

/** 主题列表 */
const themeList: ThemeList[] = [
  {
    title: "默认",
    name: DEFAULT_THEME_NAME
  },
  {
    title: "黑暗",
    name: "dark"
  }
]

/** 正在应用的主题名称 */
const activeThemeName = ref<ThemeName>(getActiveThemeName() || DEFAULT_THEME_NAME)

/**
 * 管理“到点自动切换”的定时器
 * 使用 setTimeout 在下一次边界（07:00 或 19:00）触发，触发后再次续约下一次
 */
let timeSwitchTimer: number | null = null

// 时间段常量
const DAY_START_HOUR = 7
const NIGHT_START_HOUR = 19

/** 当前时间是否处于夜间段（NIGHT_START_HOUR~24 或 0~DAY_START_HOUR） */
function isNightNow(now: Date = new Date()): boolean {
  const hour = now.getHours()
  return hour >= NIGHT_START_HOUR || hour < DAY_START_HOUR
}

/** 依据“系统优先 OR 时间段”计算自动主题 */
function computeAutoTheme(prefersDark?: boolean): ThemeName {
  const systemDark = !!prefersDark
  return systemDark || isNightNow() ? "dark" : DEFAULT_THEME_NAME
}

/** 设置主题 */
function setTheme({ clientX, clientY }: MouseEvent, value: ThemeName) {
  const maxRadius = Math.hypot(
    Math.max(clientX, window.innerWidth - clientX),
    Math.max(clientY, window.innerHeight - clientY)
  )
  setCssVar("--v3-theme-x", `${clientX}px`)
  setCssVar("--v3-theme-y", `${clientY}px`)
  setCssVar("--v3-theme-r", `${maxRadius}px`)
  const handler = () => {
    activeThemeName.value = value
    // 标记为用户主动选择
    setThemeUserOverride(true)
  }
  document.startViewTransition ? document.startViewTransition(handler) : handler()
}

/** 在 html 根元素上挂载 class */
function addHtmlClass(value: ThemeName) {
  document.documentElement.classList.add(value)
}

/** 在 html 根元素上移除其他主题 class */
function removeHtmlClass(value: ThemeName) {
  const otherThemeNameList = themeList.map(item => item.name).filter(name => name !== value)
  document.documentElement.classList.remove(...otherThemeNameList)
}

/**
 * 测试“按时间段自动切换 + 跟随系统”最简方案：
 * 1) 清理覆盖标记与主题记录并刷新：
 *    localStorage.removeItem('v3-admin-vite-theme-user-override-key');
 *    localStorage.removeItem('v3-admin-vite-active-theme-name-key');
 *    location.reload();
 * 2) 测试跟随系统：
 *    Chrome DevTools → Cmd/Ctrl+Shift+P → “Emulate CSS prefers-color-scheme: dark/light”，页面应跟随切换
 *    （仅在未手动覆盖时生效）
 * 3) 测试按时间段（19:00–07:00 为 dark）：
 *    临时修改系统时间到 19:30 或 06:30 后刷新，或检查 new Date().getHours()
 * 4) 验证结果：
 *    document.documentElement.classList 应包含 'dark' 或 'normal'
 * 5) 用户优先级：
 *    只要调用 setTheme 手动选择一次，会写入 v3-admin-vite-theme-user-override-key；
 *    之后自动策略不会再覆盖。再次测试自动策略时，重复步骤 1。
 */
/** 初始化 */
function initTheme() {
  // 1) 先根据“系统/时间”计算初始主题（仅当未被用户手动覆盖时）
  if (!getThemeUserOverride()) {
    const media = window.matchMedia?.("(prefers-color-scheme: dark)")
    const prefersDark = !!media?.matches
    activeThemeName.value = computeAutoTheme(prefersDark)

    // 跟随系统变化（仅在未手动覆盖时生效）
    if (media) {
      media.addEventListener?.("change", (e) => {
        if (!getThemeUserOverride()) {
          activeThemeName.value = computeAutoTheme(e.matches)
        }
      })
    }

    // 到点自动切换（仅在未手动覆盖时生效）
    scheduleNextTimeSwitch()
  }

  // 2) 再持久化并同步到 html class
  watchEffect(() => {
    const value = activeThemeName.value
    removeHtmlClass(value)
    addHtmlClass(value)
    setActiveThemeName(value)
  })

  // 可见性/页面恢复时进行时间策略校准（避免休眠或时间调整导致的偏差）
  const calibrate = () => {
    if (!getThemeUserOverride()) {
      applyTimeBasedThemeNow()
      scheduleNextTimeSwitch()
    }
  }
  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") calibrate()
  })
  window.addEventListener("pageshow", calibrate)
}

/** 计算距离下一次边界时间（07:00 或 19:00）的毫秒数 */
function msUntilNextBoundary(): number {
  const now = new Date()
  const year = now.getFullYear()
  const month = now.getMonth()
  const date = now.getDate()
  const currentMinutes = now.getHours() * 60 + now.getMinutes()

  const boundary1 = DAY_START_HOUR * 60 // 07:00
  const boundary2 = NIGHT_START_HOUR * 60 // 19:00

  let target = new Date(year, month, date, DAY_START_HOUR, 0, 0, 0)
  if (currentMinutes < boundary1) {
    // 下一次是今天 07:00
    target = new Date(year, month, date, DAY_START_HOUR, 0, 0, 0)
  } else if (currentMinutes < boundary2) {
    // 下一次是今天 19:00
    target = new Date(year, month, date, NIGHT_START_HOUR, 0, 0, 0)
  } else {
    // 下一次是明天 07:00
    const tomorrow = new Date(year, month, date + 1)
    target = new Date(
      tomorrow.getFullYear(),
      tomorrow.getMonth(),
      tomorrow.getDate(),
      DAY_START_HOUR,
      0,
      0,
      0
    )
  }
  return Math.max(0, target.getTime() - now.getTime())
}

/** 立即按时间策略应用主题（19:00-07:00 为 dark） */
function applyTimeBasedThemeNow() {
  const media = window.matchMedia?.("(prefers-color-scheme: dark)")
  activeThemeName.value = computeAutoTheme(media?.matches)
}

/** 调度下一次时间点切换 */
function scheduleNextTimeSwitch() {
  if (timeSwitchTimer) {
    clearTimeout(timeSwitchTimer)
    timeSwitchTimer = null
  }
  const delay = msUntilNextBoundary()
  timeSwitchTimer = window.setTimeout(() => {
    if (!getThemeUserOverride()) {
      applyTimeBasedThemeNow()
      scheduleNextTimeSwitch()
    }
  }, delay)
}

/** 主题 Composable */
export function useTheme() {
  return { themeList, activeThemeName, initTheme, setTheme }
}
